package obs;

import com.google.gson.Gson;
import com.obs.services.ObsClient;
import com.obs.services.ObsConfiguration;
import com.obs.services.exception.ObsException;
import com.obs.services.internal.utils.ServiceUtils;
import com.obs.services.model.*;

import java.io.*;
import java.net.URL;

/**
 * Title: ObjectOperationsSample
 * Description: 对象相关接口的 用法 示例
 *
 * @author hfl
 * @version V1.0
 * @date 2020-05-25
 */
public class ObjectOperationsSample {
    private static final String endPoint = "http://obs.cn-north-4.myhuaweicloud.com";
    private static final String ak = "NNNNWPW2FZHMYPRB3M79OBXXX";
    private static final String sk = "7ZRRRRX0kNN0SgsxtIsB6EBZGygWvpC04mezuT0pbBBBPu";
    private static ObsClient obsClient;
    private static String bucketName = "wuzheng-demo";
    //private static String bucketName = "temp-bucket";
    private static String objectKey = "my-obs-object-key-demo";

    //初始化obs配置
    static {
        ObsConfiguration config = new ObsConfiguration();
        config.setSocketTimeout(30000);
        config.setConnectionTimeout(10000);
        config.setEndPoint(endPoint);
        obsClient = new ObsClient(ak, sk, config);
    }


    //设置获取acl权限
    public static void doObjectAclOperations() throws ObsException {
        System.out.println("Setting object ACL to public-read \n");
        obsClient.setObjectAcl(bucketName, objectKey, AccessControlList.REST_CANNED_PUBLIC_READ);
        System.out.println("Getting object ACL " + obsClient.getObjectAcl(bucketName, objectKey) + "\n");
//        System.out.println("Setting object ACL to private \n");
//        obsClient.setObjectAcl(bucketName, objectKey, AccessControlList.REST_CANNED_PRIVATE);
//        System.out.println("Getting object ACL " + obsClient.getObjectAcl(bucketName, objectKey) + "\n");
    }

    //关闭客户端
    public static void closeClient() {
        if (obsClient != null) {
            try {
                /*
                 * Close obs client
                 */
                obsClient.close();
            } catch (IOException e) {
            }
        }
    }

    //拷贝对象
    public static void copyObject(String objectKey) {
        String sourceBucketName = bucketName;
        String destBucketName = bucketName;
        String sourceObjectKey = objectKey;
        String destObjectKey = objectKey + "-back";
        System.out.println("Copying object\n");
        CopyObjectResult result = obsClient.copyObject(sourceBucketName, sourceObjectKey, destBucketName, destObjectKey);
        System.out.println(new Gson().toJson(result));
    }

    public static void getObject() throws IOException {
        /*
         * Get object
         * 获取对象
         */
        System.out.println("Getting object content");
        ObsObject obsObject = obsClient.getObject(bucketName, objectKey, null);
        System.out.println("\tobject content:" + ServiceUtils.toString(obsObject.getObjectContent()));
    }

    public static void getObjectMetadata(String objectKey) {
        /*
         * Get object metadata
         */
        //获取对象元数据
        System.out.println("Getting object metadata");
        ObjectMetadata metadata = obsClient.getObjectMetadata(bucketName, objectKey, null);
        System.out.println("\t" + metadata);
    }

    public static void putObjectStr() throws UnsupportedEncodingException {
        // Create object 上传字符串（byte数组）
        String content = "Hello OBS";
        PutObjectResult putObjectResult = obsClient.putObject(bucketName, objectKey, new ByteArrayInputStream(content.getBytes("UTF-8")), null);
        System.out.println("Create object:" + objectKey + " successfully!\n");
        //// 读取该已上传对象的URL
        System.out.println(putObjectResult.getObjectUrl());
        System.out.println(new Gson().toJson(putObjectResult));
    }

    //上传网络流
    public static void putByInputStream() throws IOException {

//        InputStream inputStream = new URL("http://www.a.com").openStream();
        InputStream inputStream = new URL("https://csdnimg.cn/cdn/content-toolbar/csdn-logo.png").openStream();
        PutObjectResult putObjectResult = obsClient.putObject(bucketName, objectKey, inputStream);
        // 读取该已上传对象的URL
        System.out.println(putObjectResult.getObjectUrl());
        System.out.println(new Gson().toJson(putObjectResult));

    }


    //上传文件流
    public static void putObjectByFileInputStream() throws FileNotFoundException {
        FileInputStream fis = new FileInputStream(new File("E:\\text.txt"));  // 待上传的本地文件路径，需要指定到具体的文件名
        PutObjectResult putObjectResult = obsClient.putObject(bucketName, "objectname1", fis);
        // 读取该已上传对象的URL
        System.out.println(putObjectResult.getObjectUrl());
        System.out.println(new Gson().toJson(putObjectResult));
    }

    //获取文件上传的进度
    public static void putObjectByFileIoAndProgress() {
        PutObjectRequest request = new PutObjectRequest(bucketName, "objectname");
        request.setFile(new File("C:\\Users\\hufanglei\\Pictures\\timg.jpg"));
        request.setProgressListener(new ProgressListener() {
            public void progressChanged(ProgressStatus status) {
                // 获取上传平均速率
                System.out.println("AverageSpeed:" + status.getAverageSpeed());
                // 获取上传进度百分比
                System.out.println("TransferPercentage:" + status.getTransferPercentage());
            }
        });
        // 每上传1MB数据反馈上传进度
        // request.setProgressInterval(1024 * 1024L);
        request.setProgressInterval(1024 * 12L);
        obsClient.putObject(request);
    }

    //设置文件长度
    public static void setObjectLength() {
        ObjectMetadata metadata = new ObjectMetadata();
        metadata.setContentLength(1024 * 1024L);// 1MB
        PutObjectResult result = obsClient.putObject(bucketName, "objectname",
                new File("C:\\Users\\hufanglei\\Pictures\\timg.jpg"), metadata);
        System.out.println(new Gson().toJson(result));

    }

    //设置对象MD5值
    public static void setObjectMd5() {
        // 上传图片
        ObjectMetadata metadata = new ObjectMetadata();
        metadata.setContentMd5("your md5 which should be encoded by base64");
        obsClient.putObject(bucketName, "objectname", new File("C:\\Users\\hufanglei\\Pictures\\timg.jpg"), metadata);
    }

    //设置对象自定义元数据
    public static void setObjectMeta() {
        ObjectMetadata metadata = new ObjectMetadata();
        metadata.addUserMetadata("property1", "property-value1");
        metadata.getMetadata().put("property2", "property-value2");
        PutObjectResult result = obsClient.putObject(bucketName, "objectname",
                new File("C:\\Users\\hufanglei\\Pictures\\timg.jpg"), metadata);
        System.out.println(new Gson().toJson(result));
    }


    public static void main(String[] args) throws IOException {
        //上传字符串（byte数组）
        //putObjectStr();
        //获取对象
        //getObject();
        //拷贝对象
        //copyObject("MyObjectKey1/");
        //设置获取acl权限
        //doObjectAclOperations();
        //上传网络流
         //putByInputStream();
        //上传文件流
        //putObjectByFileInputStream();
        //获取文件上传的进度
        //putObjectByFileIoAndProgress();
        //设置文件长度
        //setObjectLength();
        //设置对象MD5值
        //setObjectMd5();
        //设置对象自定义元数据
        //setObjectMeta();
        //获取对象元数据
        //getObjectMetadata("objectname");
        //获取对象属性
        //getObjectMeta();
        //-管理对象访问权限
        //// 方式1：上传对象时指定预定义访问策略
        //putObjectPreAccessStrategy();
        //// 未测试 方式2：设置对象访问权限为私有读写
        //putClientStrategy();
        ///// 未测试 方式3：直接设置对象访问权限
        //directPutObjectAcl();
        ////获取对象访问权限
        //getObjectAcl();
        //列举对象
        ////重要: 简单列举
       //  simpleListObjects(bucketName);
        ////指定数目列举
        //listObjects(bucketName, 3);
        ////指定前缀列举
        //listObjectsByPrefix(bucketName, 3, "my-obs");
        ////指定起始位置列举(不大明白)
        //listObjectsStartEnd(bucketName, 100, "back");
        //分页列举全部对象
        //listObjectsByPage(bucketName,2);
        //列举文件夹中的所有对象
        //listObjectsByFolder(bucketName, "MyObjectKey1/");
        //按文件夹分组列举所有对象
        //listObjectsByGroup(bucketName);
        //删除单个对象 MyObjectKey1/-back
        //deletObj(bucketName, "MyObjectKey1/-back");
        //批量删除
        delObjectsAll(bucketName);
        //listObjectsByGroup(bucketName);
        //文件上传时设置 MIME 文件托管 ( 上传对象，设置对象MIME类型)
         setstaticView(bucketName);
        //配置默认主页和错误页面(未测试)
        //staticDefaultHtml();
        //查看网站托管（报错）
        staticView(bucketName);

    }

    private static void staticView(String bucketname) {
        WebsiteConfiguration config = obsClient.getBucketWebsite(bucketname);
        System.out.println("\t" + config.getKey());
        System.out.println("\t" + config.getSuffix());
        for(RouteRule rule : config.getRouteRules()){
            System.out.println("\t" +rule);
        }
    }


    //配置默认主页和错误页面(未测试)
    private static void staticDefaultHtml() {
        WebsiteConfiguration config = new WebsiteConfiguration();
        // 配置默认主页
        config.setSuffix("index.html");
        // 配置错误页面
        config.setKey("error.html");
        obsClient.setBucketWebsite("bucketname", config);
    }

    public static void setstaticView(String bucketname) {
        PutObjectRequest request = new PutObjectRequest();
        request.setBucketName(bucketname);
        request.setObjectKey("index.html");
        request.setFile(new File("E:\\index.html"));
        ObjectMetadata metadata = new ObjectMetadata();
        metadata.setContentType("text/html");
        request.setMetadata(metadata);
        PutObjectResult result = obsClient.putObject(request);
        System.out.println(result);
        // 设置对象访问权限为公共读
        HeaderResponse response = obsClient.setObjectAcl(bucketname, "index.html", AccessControlList.REST_CANNED_PUBLIC_READ);
        System.out.println(response);
    }

    private static void delObjectsAll(String bucketName) {
        ListVersionsRequest request = new ListVersionsRequest(bucketName);
        // 每次批量删除100个对象
        request.setMaxKeys(100);
        ListVersionsResult result;
        do {
            result = obsClient.listVersions(request);
            DeleteObjectsRequest deleteRequest = new DeleteObjectsRequest(bucketName);
            for(VersionOrDeleteMarker v  : result.getVersions()) {
                deleteRequest.addKeyAndVersion(v.getKey(), v.getVersionId());
            }
            DeleteObjectsResult deleteResult = obsClient.deleteObjects(deleteRequest);
            // 获取删除成功的对象
            System.out.println(deleteResult.getDeletedObjectResults());
            // 获取删除失败的对象
            System.out.println(deleteResult.getErrorResults());
            request.setKeyMarker(result.getNextKeyMarker());
            request.setVersionIdMarker(result.getNextVersionIdMarker());
        }while(result.isTruncated());
    }

    ////删除单个对象 MyObjectKey1/-back
    private static void deletObj(String bucketName, String objectKey) {
        DeleteObjectResult result = obsClient.deleteObject(bucketName, objectKey);
        System.out.println(new Gson().toJson(result));
    }

    ////按文件夹分组列举所有对象
    private static void listObjectsByGroup(String bucketname) {
        ListObjectsRequest request = new ListObjectsRequest(bucketname);
        request.setMaxKeys(1000);
     // 设置文件夹分隔符"/"
        request.setDelimiter("/");
        ObjectListing result = obsClient.listObjects(request);
        System.out.println("Objects in the root directory:");
        for(ObsObject obsObject : result.getObjects()){
            System.out.println("\t" + obsObject.getObjectKey());
            System.out.println("\t" + obsObject.getOwner());
        }
        listObjectsByPrefix(obsClient, request, result);
    }
    private static void listObjectsByPrefix(ObsClient obsClient, ListObjectsRequest request, ObjectListing result) throws ObsException
    {
        for(String prefix : result.getCommonPrefixes()){
            System.out.println("Objects in folder [" + prefix + "]:");
            request.setPrefix(prefix);
            result  = obsClient.listObjects(request);
            for(ObsObject obsObject : result.getObjects()){
                System.out.println("\t" + obsObject.getObjectKey());
                System.out.println("\t" + obsObject.getOwner());
            }
            listObjectsByPrefix(obsClient, request, result);
        }
    }

    //列举文件夹中的所有对象
    public static void listObjectsByFolder(String bucketname, String folderPrefix) {
        ListObjectsRequest request = new ListObjectsRequest(bucketname);
        // 设置文件夹对象名"dir/"为前缀
//        request.setPrefix("dir/");
        request.setPrefix(folderPrefix);
        //列举文件个数
        request.setMaxKeys(1000);
        ObjectListing result;
        do{
            result = obsClient.listObjects(request);
            for (ObsObject obsObject : result.getObjects())
            {
                System.out.println("\t" + obsObject.getObjectKey());
                System.out.println("\t" + obsObject.getOwner());
            }
            request.setMarker(result.getNextMarker());
        }while(result.isTruncated());
    }

    //分页列举全部对象
    public static void listObjectsByPage(String bucketname,Integer pageSize) {
        ListObjectsRequest request = new ListObjectsRequest(bucketname);
        // 设置每页100个对象
        request.setMaxKeys(pageSize);
        ObjectListing result;
        do{
            result = obsClient.listObjects(request);
            for(ObsObject obsObject : result.getObjects()){
                System.out.println("\t" + obsObject.getObjectKey());
                System.out.println("\t" + obsObject.getOwner());
            }
            request.setMarker(result.getNextMarker());
        }while(result.isTruncated());
        //关闭客户端
        closeClient();
    }

    //指定起始位置列举
    public static void listObjectsStartEnd(String bucketname,Integer num, String marker) {
        ListObjectsRequest request = new ListObjectsRequest(bucketname);
        // 设置列举对象名字典序在"test"之后的100个对象
        // request.setMaxKeys(100);
        request.setMaxKeys(num);
        // request.setMarker("test");
        request.setMarker(marker);
        ObjectListing result = obsClient.listObjects(request);
        for(ObsObject obsObject : result.getObjects()){
            System.out.println("\t" + obsObject.getObjectKey());
            System.out.println("\t" + obsObject.getOwner());
        }
    }

    //指定前缀列举
    public static void listObjectsByPrefix(String bucketname, Integer num, String prefix) {
        ListObjectsRequest request = new ListObjectsRequest(bucketname);
        // 设置列举带有prefix前缀的100个对象
        request.setMaxKeys(num);
        request.setPrefix(prefix);
        ObjectListing result = obsClient.listObjects(request);
        for(ObsObject obsObject : result.getObjects()){
            System.out.println("\t" + obsObject.getObjectKey());
            System.out.println("\t" + obsObject.getOwner());
        }
    }

    //指定数目列举
    public static void listObjects(String bucketname, Integer num) {
        ListObjectsRequest request = new ListObjectsRequest(bucketname);
        // 只列举100个对象
        request.setMaxKeys(num);
        ObjectListing result = obsClient.listObjects(request);
        for (ObsObject obsObject : result.getObjects()) {
            System.out.println("\t" + obsObject.getObjectKey());
            System.out.println("\t" + obsObject.getOwner());
        }
    }

    //简单列举
    public static void simpleListObjects(String bucketname) {
        ObjectListing result = obsClient.listObjects(bucketname);
        for (ObsObject obsObject : result.getObjects()) {
            System.out.println("\t" + obsObject.getObjectKey());
            System.out.println("\t" + obsObject.getOwner());
        }
    }

    //获取对象访问权限
    private static void getObjectAcl() {
        AccessControlList acl = obsClient.getObjectAcl(bucketName, "objectname");
        System.out.println(acl);
    }

    //直接设置对象访问权限
    private static void directPutObjectAcl() {
        AccessControlList acl = new AccessControlList();
        Owner owner = new Owner();
        owner.setId("ownerid");
        acl.setOwner(owner);
        // 为指定用户设置完全控制权限
        acl.grantPermission(new CanonicalGrantee("userid"), Permission.PERMISSION_FULL_CONTROL);
        // 为所有用户设置读权限
        acl.grantPermission(GroupGrantee.ALL_USERS, Permission.PERMISSION_READ);
        obsClient.setObjectAcl("bucketname", "objectname", acl);
    }

    private static void putClientStrategy() {
        obsClient.setObjectAcl(bucketName, "objectname", AccessControlList.REST_CANNED_PRIVATE);
    }

    //很重要: 上传对象时指定预定义访问策略
    private static void putObjectPreAccessStrategy() {
        PutObjectRequest request = new PutObjectRequest();
        request.setBucketName(bucketName);
        request.setObjectKey("objectname1/text");
//        request.setFile(new File("C:\\Users\\hufanglei\\Pictures\\timg.jpg"));
//        request.setFile(new File("C:\\Users\\hufanglei\\Pictures\\timg.jpg"));
        request.setFile(new File("E:\\text.docx"));
        //设置对象访问权限为公共读
        request.setAcl(AccessControlList.REST_CANNED_PUBLIC_READ);
        PutObjectResult result = obsClient.putObject(request);
        System.out.println(new Gson().toJson(result));
    }

    private static void getObjectMeta() {
        ObjectMetadata metadata = obsClient.getObjectMetadata(bucketName, "objectname");
        System.out.println("\t" + metadata.getContentType());
        System.out.println("\t" + metadata.getContentLength());
        System.out.println("\t" + metadata.getUserMetadata("property"));
    }


}
